#include <am.h>
#include <nemu.h>

#define SYNC_ADDR (VGACTL_ADDR + 4)
#define HEIGHT_MASK 0x0000FFFF


void __am_gpu_init() {
  uint32_t size = inl(VGACTL_ADDR);
  int height = size & HEIGHT_MASK;
  int width = size >> 16;
  uint32_t *fb = (uint32_t *)(uintptr_t)FB_ADDR;
  for (int i = 0; i < width * height; i ++) fb[i] = i;
  outl(SYNC_ADDR, 1);

}

void __am_gpu_config(AM_GPU_CONFIG_T *cfg) {
  uint32_t size = inl(VGACTL_ADDR);
  *cfg = (AM_GPU_CONFIG_T) {
    .present = true, .has_accel = false,
    .width = size >> 16, .height = size & HEIGHT_MASK,
    .vmemsz = (size >> 16) * (size & HEIGHT_MASK)
  };
}

void __am_gpu_fbdraw(AM_GPU_FBDRAW_T *ctl) {
  uint32_t size = inl(VGACTL_ADDR);
  int height = size & HEIGHT_MASK;
  int width = size >> 16;
  uint32_t *fb = (uint32_t *)(uintptr_t)FB_ADDR;
  uint32_t *img = (uint32_t *)ctl->pixels;
  int off;
  for (int i = 0; i < ctl->h; i++) {
    for (int j = 0; j < ctl->w; j++) {
      off = ctl->x + j + (ctl->y + i) * width;
      if(off < width * height)
        *(fb + off) = *(img + i * ctl->w + j);
    }
  }
  if (ctl->sync) {
    outl(SYNC_ADDR, 1);
  }
}

void __am_gpu_status(AM_GPU_STATUS_T *status) {
  status->ready = true;
}
